/*
 *  Vector.h
 *  zray-gui
 *
 *  Created by czalkin on 1/10/09.
 *  Copyright 2009 __MyCompanyName__. All rights reserved.
 *
 */

#ifndef VECTOR3_H_
#define VECTOR3_H_

#include "Point3.hpp"
#include <cmath>

class Point3;

class Vector3
{
	friend class Vector4;
	friend class Matrix4;
	friend class Point3;
	
public:
	Vector3() { v[0] = 0; v[1] = 0; v[2] = 0; }
	Vector3( float x, float y, float z ) { v[0] = x; v[1] = y; v[2] = z; }
	Vector3( float* in ) { v[0] = in[0]; v[1] = in[1]; v[2] = in[2]; }
	
	Vector3( const Point3 &pt );
	
	Vector3 reflect( const Vector3 &normal ) const;
	
	float operator[]( const int index ) const { return v[index]; }
	
	inline void set( const int index, float val ) { v[index] = val; }
	inline float get( const int index ) const { return v[index]; }
	
	
	inline Vector3 cross( const Vector3 &rhs ) const
	{
		return Vector3( v[1]*rhs.v[2] - v[2]*rhs.v[1],
					   v[2]*rhs.v[0] - v[0]*rhs.v[2],
					   v[0]*rhs.v[1] - v[1]*rhs.v[0] );
	}
	
	inline Vector3& operator+=( const Vector3 &rhs )
	{
		v[0] += rhs.v[0];
		v[1] += rhs.v[1];
		v[2] += rhs.v[2];
		return *this;
	}
	
	inline Vector3 operator*=( const float s )
	{
		v[0] *= s;
		v[1] *= s;
		v[2] *= s;
		return *this;
	}
	
	inline Vector3 operator+( const Vector3 &rhs ) const
	{
		return Vector3( v[0] + rhs.v[0], v[1] + rhs.v[1], v[2] + rhs.v[2] );
	}
	
	inline Vector3 operator*( const float s ) const
	{
		return Vector3( v[0]*s, v[1]*s, v[2]*s );
	}
	
	inline Vector3 operator-( const Vector3 &rhs ) const
	{
		return Vector3( v[0] - rhs.v[0], v[1] - rhs.v[1], v[2] - rhs.v[2] );
	}
	
	inline float dot( const Vector3 &rhs ) const
	{
		return v[0]*rhs.v[0] + v[1]*rhs.v[1] + v[2]*rhs.v[2];
	}

	float dot( const Point3 &rhs ) const;
	
	inline float lengthSq() const
	{
		return v[0]*v[0] + v[1]*v[1] + v[2]*v[2];
	}
	
	inline float length() const
	{
		return sqrt( lengthSq() );
	}
	
	inline float normalize_inPlace()
	{
		const float len = length();
		v[0] /= len;
		v[1] /= len;
		v[2] /= len;
		return len;
	}
	
	inline Vector3 normalize() const
	{
		const float len = length();
		return Vector3( v[0] / len, v[1] / len, v[2] /len );
	}
	

protected:
	float v[3];
};



#endif

